package com.xhwl.logistics.converter.mapstruct;

import com.google.common.base.Strings;
import com.xhwl.common.dto.cent.vehicle.feign.CreateVehicleAccessRecordForInFeignDTO;
import com.xhwl.common.dto.cent.vehicle.feign.CreateVehicleAccessRecordForInNanTouFeignDTO;
import com.xhwl.common.dto.cent.vehicle.feign.CreateVehicleAccessRecordForOutFeignDTO;
import com.xhwl.common.dto.cent.vehicle.feign.CreateVehicleAccessRecordForOutNanTouFeignDTO;
import com.xhwl.common.dto.cent.vehicle.feign.VehicleAccessRecordQuery;
import com.xhwl.common.dto.cent.vehicle.feign.VehiclePageQuery;
import com.xhwl.common.enums.vehicle.InOutEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.logistics.bo.VehicleAccessRecordBO;
import com.xhwl.logistics.bo.cent.ProjectBO;
import com.xhwl.logistics.bo.input.QueryVehicleAccessRecordBO;
import com.xhwl.logistics.bo.input.QueryVehicleAccessRecordForCountBO;
import com.xhwl.logistics.bo.input.QueryVehicleAccessRecordSecondBO;
import com.xhwl.logistics.bo.input.QueryVehicleOvernightConditionBO;
import com.xhwl.logistics.dto.query.CarInJieShunDTO;
import com.xhwl.logistics.dto.query.CarOutJieShunDTO;
import com.xhwl.logistics.dto.query.PageDTO;
import com.xhwl.logistics.dto.query.VehicleAccessRecordDTO;
import com.xhwl.logistics.entity.VehicleAccessRecord;
import com.xhwl.logistics.enums.VehicleCardTypeEnum;
import com.xhwl.logistics.enums.VehiclePassTypeEnum;
import com.xhwl.logistics.po.VehicleAccessRecordPO;
import com.xhwl.logistics.util.AboutDateUtil;
import com.xhwl.logistics.vo.VehicleAccessRecordSecondVO;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.NullValueMappingStrategy;
import org.springframework.data.util.Optionals;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Mapper(componentModel = "spring", nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)
public interface VehicleAccessRecordConverter {

    @Getter
    @AllArgsConstructor
    enum JieShunCardTypeEnum {
        JIE_SHUN_TEMP_CARD("TEMPCARD", 3),
        JIE_SHUN_MONTH_CARD("MONTHCARD", 1);
        private String jieShunCardType;
        private Integer centCardType;
        public static JieShunCardTypeEnum toJieShunCardTypeEnum(String jieShunCardType) {
            for (JieShunCardTypeEnum jieShunCardTypeEnum : JieShunCardTypeEnum.values()) {
                if (jieShunCardTypeEnum.jieShunCardType.equals(jieShunCardType)) {
                    return jieShunCardTypeEnum;
                }
            }
            throw new BusinessException("捷顺回调目前只支持临时卡和月卡的转换");
        }
    }

    //*********Data Push JieShun*********
    default VehicleAccessRecord jieShun2VehicleAccessRecord(ProjectBO projectBO, CarInJieShunDTO carInJieShunDTO, Integer status) {
        VehicleAccessRecord vehicleAccessRecord = toVehicleAccessRecord(projectBO, carInJieShunDTO, status);
        vehicleAccessRecord.setCardType(JieShunCardTypeEnum.toJieShunCardTypeEnum(carInJieShunDTO.getCardType()).centCardType);
        return vehicleAccessRecord;
    }

    @Mapping(source = "carInJieShunDTO.parkCode", target = "parkId")
    @Mapping(source = "carInJieShunDTO.carNumber", target = "plateNumber")
    @Mapping(source = "carInJieShunDTO.inTime", target = "enterTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(source = "carInJieShunDTO.itemId", target = "recordId")
    @Mapping(target = "cardType", ignore = true)
    VehicleAccessRecord toVehicleAccessRecord(ProjectBO projectBO, CarInJieShunDTO carInJieShunDTO, Integer status);

    @Mapping(source = "carOutJieShunDTO.outTime", target = "exitTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(target = "cardType", ignore = true)
    VehicleAccessRecord toVehicleAccessRecord(CarOutJieShunDTO carOutJieShunDTO, Integer id, Integer status);

    default VehicleAccessRecord jieShun2VehicleAccessRecord(ProjectBO projectBO, CarOutJieShunDTO carOutJieShunDTO, Integer status) {
        VehicleAccessRecord vehicleAccessRecord = toVehicleAccessRecord(projectBO, carOutJieShunDTO, status);
        vehicleAccessRecord.setCardType(JieShunCardTypeEnum.toJieShunCardTypeEnum(carOutJieShunDTO.getCardType()).centCardType);
        return vehicleAccessRecord;
    }

    @Mapping(source = "carOutJieShunDTO.parkCode", target = "parkId")
    @Mapping(source = "carOutJieShunDTO.carNumber", target = "plateNumber")
    @Mapping(source = "carOutJieShunDTO.outTime", target = "exitTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(source = "carOutJieShunDTO.inRecordId", target = "recordId")
    @Mapping(target = "cardType", ignore = true)
    VehicleAccessRecord toVehicleAccessRecord(ProjectBO projectBO, CarOutJieShunDTO carOutJieShunDTO, Integer status);

    //*********feign*********
    VehicleAccessRecord toVehicleAccessRecord(CreateVehicleAccessRecordForInFeignDTO createVehicleAccessRecordForInFeignDTO, Integer status, String projectName, String projectCode);

    VehicleAccessRecord toVehicleAccessRecord(CreateVehicleAccessRecordForOutFeignDTO createVehicleAccessRecordForOutFeignDTO, Integer status, String projectName, String projectCode);

    @Mapping(target = "projectId", ignore = true)
    @Mapping(target = "parkId", ignore = true)
    @Mapping(target = "plateNumber", ignore = true)
    @Mapping(target = "cardType", ignore = true)
    @Mapping(target = "recordId", ignore = true)
    VehicleAccessRecord toVehicleAccessRecord(CreateVehicleAccessRecordForOutFeignDTO createVehicleAccessRecordForOutFeignDTO, Integer id, Integer status);

    default List<VehicleAccessRecord> toVehicleAccessRecordList(List<CreateVehicleAccessRecordForInNanTouFeignDTO> createVehicleAccessRecordForInNanTouFeignDTOList, ProjectBO projectBO) {
        return createVehicleAccessRecordForInNanTouFeignDTOList.stream()
                .map(createVehicleAccessRecordForInNanTouFeignDTO -> toVehicleAccessRecord(createVehicleAccessRecordForInNanTouFeignDTO, projectBO))
                .collect(Collectors.toList());
    }

    @Mapping(target = "enterPassageName", source = "createVehicleAccessRecordForInNanTouFeignDTO.enterPassage")
    @Mapping(target = "projectId", source = "projectBO.projectId")
    @Mapping(target = "projectCode", source = "projectBO.projectCode")
    @Mapping(target = "projectName", source = "projectBO.projectName")
    VehicleAccessRecord toVehicleAccessRecord(CreateVehicleAccessRecordForInNanTouFeignDTO createVehicleAccessRecordForInNanTouFeignDTO, ProjectBO projectBO);

    @Mapping(target = "enterPassageName", source = "createVehicleAccessRecordForOutNanTouFeignDTO.enterPassage")
    @Mapping(target = "exitPassageName", source = "createVehicleAccessRecordForOutNanTouFeignDTO.exitPassage")
    @Mapping(target = "projectId", source = "projectBO.projectId")
    @Mapping(target = "projectCode", source = "projectBO.projectCode")
    @Mapping(target = "projectName", source = "projectBO.projectName")
    VehicleAccessRecord toVehicleAccessRecord(CreateVehicleAccessRecordForOutNanTouFeignDTO createVehicleAccessRecordForOutNanTouFeignDTO, ProjectBO projectBO);

    default VehicleAccessRecord toVehicleAccessRecord(CreateVehicleAccessRecordForOutNanTouFeignDTO createVehicleAccessRecordForOutNanTouFeignDTO, Integer id) {
        VehicleAccessRecord vehicleAccessRecord = new VehicleAccessRecord();
        vehicleAccessRecord.setId(id);
        vehicleAccessRecord.setExitTime(createVehicleAccessRecordForOutNanTouFeignDTO.getExitTime());
        vehicleAccessRecord.setExitType(createVehicleAccessRecordForOutNanTouFeignDTO.getExitType());
        vehicleAccessRecord.setExitPictureUrl(createVehicleAccessRecordForOutNanTouFeignDTO.getExitPictureUrl());
        vehicleAccessRecord.setExitPassageName(createVehicleAccessRecordForOutNanTouFeignDTO.getExitPassage());
        vehicleAccessRecord.setStatus(createVehicleAccessRecordForOutNanTouFeignDTO.getStatus());
        return vehicleAccessRecord;
    }

    QueryVehicleAccessRecordBO vehicleAccessRecordQuery2QueryVehicleAccessRecordBO(VehicleAccessRecordQuery vehicleAccessRecordQuery);

    PageDTO vehiclePageQuery2PageDTO(VehiclePageQuery vehiclePageQuery);

    //************Query BO <- Controller DTO************
    default QueryVehicleAccessRecordBO toQueryVehicleAccessRecordBO(VehicleAccessRecordDTO vehicleAccessRecordDTO, int day, int hour, int minute) {
        QueryVehicleAccessRecordBO queryVehicleAccessRecordBO = vehicleAccessRecordDTO2QueryVehicleAccessRecordBO(vehicleAccessRecordDTO);

        String passType = vehicleAccessRecordDTO.getPassType();
        if (!Strings.isNullOrEmpty(passType)) {
            queryVehicleAccessRecordBO.setVehiclePassTypeEnum(VehiclePassTypeEnum.toVehiclePassTypeEnum(passType));
        }

        if (null!=vehicleAccessRecordDTO.getOvernight()) {
            QueryVehicleOvernightConditionBO queryVehicleOvernightConditionBO = new QueryVehicleOvernightConditionBO();
            queryVehicleOvernightConditionBO.setOvernight(vehicleAccessRecordDTO.getOvernight());
            queryVehicleOvernightConditionBO.setMysqlTemporalIntervalExpression(day + " " + hour + ":" + minute);
            queryVehicleAccessRecordBO.setQueryVehicleOvernightConditionBO(queryVehicleOvernightConditionBO);
        }
        return queryVehicleAccessRecordBO;
    }
    QueryVehicleAccessRecordBO vehicleAccessRecordDTO2QueryVehicleAccessRecordBO(VehicleAccessRecordDTO vehicleAccessRecordDTO);

    QueryVehicleAccessRecordSecondBO vehicleAccessRecordDTO2QueryVehicleAccessRecordSecondBO(VehicleAccessRecordDTO vehicleAccessRecordDTO);
    //************Query BO <- Controller DTO************


    //************BO <- PO************
    default List<VehicleAccessRecordBO> vehicleAccessRecordPOList2VehicleAccessRecordBOList(List<VehicleAccessRecordPO> vehicleAccessRecordPOList) {
        return vehicleAccessRecordPOList.stream().map(this::toVehicleAccessRecordBO).collect(Collectors.toList());
    }
    default VehicleAccessRecordBO toVehicleAccessRecordBO(VehicleAccessRecordPO vehicleAccessRecordPO) {
        VehicleAccessRecordBO vehicleAccessRecordBO = vehicleAccessRecordPO2VehicleAccessRecordBO(vehicleAccessRecordPO);

        Integer cardType = vehicleAccessRecordPO.getCardType();
        Integer enterType = vehicleAccessRecordPO.getEnterType();
        Integer exitType = vehicleAccessRecordPO.getExitType();
        Optionals.ifPresentOrElse(
                Optional.ofNullable(cardType),
                card -> vehicleAccessRecordBO.setCardType(VehicleCardTypeEnum.toVehicleCardTypeEnum(card).getDescription()),
                () -> vehicleAccessRecordBO.setCardType(VehicleCardTypeEnum.TEMPORARILY.getDescription()));

        Optionals.ifPresentOrElse(
                Optional.ofNullable(enterType),
                enter -> vehicleAccessRecordBO.setEnterType(VehiclePassTypeEnum.toVehiclePassTypeEnum(enter).getDescription()),
                () -> vehicleAccessRecordBO.setEnterType(VehiclePassTypeEnum.NORMAL.getDescription()));

        Optionals.ifPresentOrElse(
                Optional.ofNullable(exitType),
                exit -> vehicleAccessRecordBO.setExitType(VehiclePassTypeEnum.toVehiclePassTypeEnum(exit).getDescription()),
                () -> {
                    if (1 == vehicleAccessRecordPO.getStatus()) {
                        vehicleAccessRecordBO.setExitType(VehiclePassTypeEnum.NORMAL.getDescription());
                    }
                });

        return vehicleAccessRecordBO;
    }
    @Mapping(target = "cardType", ignore = true)
    @Mapping(target = "enterType", ignore = true)
    @Mapping(target = "exitType", ignore = true)
    VehicleAccessRecordBO vehicleAccessRecordPO2VehicleAccessRecordBO(VehicleAccessRecordPO vehicleAccessRecordPO);
    //************BO <- PO************


    default QueryVehicleAccessRecordForCountBO toQueryVehicleAccessRecordForCountBOForEnter(Integer projectId, String parkId, Date enterTime) {
        QueryVehicleAccessRecordForCountBO queryVehicleAccessRecordForCountBO = new QueryVehicleAccessRecordForCountBO();
        queryVehicleAccessRecordForCountBO.setProjectId(projectId);
        queryVehicleAccessRecordForCountBO.setParkId(parkId);
        queryVehicleAccessRecordForCountBO.setEnterStartTime(enterTime);
        queryVehicleAccessRecordForCountBO.setEnterEndTime(AboutDateUtil.datePlusHour(enterTime, 1));
        return queryVehicleAccessRecordForCountBO;
    }

    default QueryVehicleAccessRecordForCountBO toQueryVehicleAccessRecordForCountBOForGoOut(Integer projectId, String parkId, Date goOutTime) {
        QueryVehicleAccessRecordForCountBO queryVehicleAccessRecordForCountBO = new QueryVehicleAccessRecordForCountBO();
        queryVehicleAccessRecordForCountBO.setProjectId(projectId);
        queryVehicleAccessRecordForCountBO.setParkId(parkId);
        queryVehicleAccessRecordForCountBO.setGoOutStartTime(goOutTime);
        queryVehicleAccessRecordForCountBO.setGoOutEndTime(AboutDateUtil.datePlusHour(goOutTime, 1));
        return queryVehicleAccessRecordForCountBO;
    }

    /**
     * VehicleAccessRecord的List转换为VehicleAccessRecordSecondVO的List
     */
    default List<VehicleAccessRecordSecondVO> toVehicleAccessRecordSecondVOList(List<VehicleAccessRecord> vehicleAccessRecordList){
        return vehicleAccessRecordList.stream().map(
                this::toVehicleAccessRecordSecondVO
        ).collect(Collectors.toList());
    }

    /**
     * VehicleAccessRecord转换为VehicleAccessRecordSecondVO
     */
    default VehicleAccessRecordSecondVO toVehicleAccessRecordSecondVO(VehicleAccessRecord vehicleAccessRecord){
        VehicleAccessRecordSecondVO vehicleAccessRecordSecondVO = new VehicleAccessRecordSecondVO();
        vehicleAccessRecordSecondVO.setPlateNumber(vehicleAccessRecord.getPlateNumber());
        if (vehicleAccessRecord.getStatus()==0){
            vehicleAccessRecordSecondVO.setPassageName(vehicleAccessRecord.getEnterPassageName());
            vehicleAccessRecordSecondVO.setStatus(InOutEnum.IN.getDisplay());
            vehicleAccessRecordSecondVO.setInOutTime(vehicleAccessRecord.getEnterTime());
        }else{
            vehicleAccessRecordSecondVO.setPassageName(vehicleAccessRecord.getExitPassageName());
            vehicleAccessRecordSecondVO.setStatus(InOutEnum.OUT.getDisplay());
            vehicleAccessRecordSecondVO.setInOutTime(vehicleAccessRecord.getExitTime());
        }
        vehicleAccessRecordSecondVO.setCardType(VehicleCardTypeEnum.toVehicleCardTypeEnum(vehicleAccessRecord.getCardType()).getDescription());
        return vehicleAccessRecordSecondVO;
    }

}
